下載模型大多是為了 fine-tune 使用,由於模型大小會受限於硬體資源,如果希望產品有更好的回答效果,大多會嘗試使用模型開發商所提供的 API 來串接它們所提供的雲端 LLM 模型。
而如何將 LLM 串接到自己的程式碼當中,接觸過 Gen AI 開發就一定使用過 Langchain,簡單來說可以實體化各個 components,然而 Langchain 強大的地方在於可以透過設計 chain 的方式將不同的 components 串接在一起,接下來三天著重在 chain 的設計上,以及自己在開發過程中踩過的雷。
Picture Source
這裡有一個簡單清楚,但功能已經算是很完整的 RAG Process Flow,Langchain 強大的地方就在於已經為中間的所有組件與連結建立好解決方案,而每一個組件又可以從這個清單中簡單的替換成其他解決方案。
讓我們簡單順過架構圖,之後進入到系統設計課程也會更快上手:
要能夠善用上述元件,組合設計出產品架構圖,就必須先了解 Runnable 概念,可以將上述的所有組件和 chain 都是為一個 Runnable (可執行組件)
透過遵守 Runnable Protocol
建立共同的存取方式,而這些 Runnable
則可以透過 Sequences
, Parallel
, Passthrough
等方式串接成鏈,最後透過 Runnable Interface
的指令將變數輸入進整條 chain 當中,今天先介紹其中 Runnable Interface
。
Runnable Interface 是為開發者提供,與模型或 chain 互動的統一介面。
主要有以下三種,又可以分為同步和異步場景。
示範前我們先定義 llm 和 chain:
from langchain_mistralai import ChatMistralAI
from langchain.prompts import ChatPromptTemplate
llm = ChatMistralAI(model="mistral-large-latest")
prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
chain = prompt | llm
chain.invoke({"topic":"SI Dream Engineering"})
await chain.ainvoke({"topic":"SI Dream Engineering"})
'''
output: AIMessage(content='What do you call a sleep-deprived engineer?\n\nA "Si-esta" engineer!', response_metadata={'token_usage': {'prompt_tokens': 11, 'total_tokens': 33, 'completion_tokens': 22}, 'model': 'mistral-large-latest', 'finish_reason': 'stop'}, id='ID', usage_metadata={'input_tokens': 11, 'output_tokens': 22, 'total_tokens': 33})
'''
chain.batch([{"topic":"SI"},{"topic":"Dream"},{"topic":"Engineering"}])
await chain.abatch([{"topic":"SI"},{"topic":"Dream"},{"topic":"Engineering"}])
'''
output:
[AIMessage(content='... joke of SI ...', response_metadata={'token_usage': {'prompt_tokens': 9, 'total_tokens': 89, 'completion_tokens': 80}, 'model': 'mistral-large-latest', 'finish_reason': 'stop'}, id='ID', usage_metadata={'input_tokens': 9, 'output_tokens': 80, 'total_tokens': 89}),
AIMessage(content='... joke of Dream ...', response_metadata={'token_usage': {'prompt_tokens': 9, 'total_tokens': 28, 'completion_tokens': 19}, 'model': 'mistral-large-latest', 'finish_reason': 'stop'}, id='ID', usage_metadata={'input_tokens': 9, 'output_tokens': 19, 'total_tokens': 28}),
AIMessage(content='... joke of Engineering ...', response_metadata={'token_usage': {'prompt_tokens': 9, 'total_tokens': 26, 'completion_tokens': 17}, 'model': 'mistral-large-latest', 'finish_reason': 'stop'}, id='ID', usage_metadata={'input_tokens': 9, 'output_tokens': 17, 'total_tokens': 26})]
'''
for s in chain.stream({"topic":"SI Dream Engineering"}):
print(s.content, end="", flush=True)
async for s in chain.astream({"topic":"SI Dream Engineering"}):
print(s.content, end="", flush=True)
'''
output:
Sure, here's a light-hearted joke for you:
Why don't SI Dream Engineers play cards in the jungle?
Because there are too many cheetahs!
(It's a play on words: "cheetahs" sounds like "cheaters")
'''
ref.